home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-13
/
mewin10s.zip
/
MSWFONT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-12
|
20KB
|
599 lines
/* The routines in this file provide font control functions under
the Microsoft Windows environment on an IBM-PC or compatible
computer.
Must be compiled with Borland C++ 2.0.
It should not be compiled if the WINDOW_MSWIN symbol is not set */
#include "estruct.h"
#include <stdio.h>
#include "eproto.h"
#include "edef.h"
#include "mswin.h"
extern char *itoa (int value, char *string, int radix);
extern int atoi (char *s);
static TEXTMETRIC Metrics;
static HFONT hNewFont;
static char FaceName[LF_FACESIZE];
/* SelectFont: Selects the emacs-chosen font in the Device Context */
/* ========== */
HFONT far pascal SelectFont (HDC hDC, HFONT hFont)
/* just like SelectObject, this function returns the previously selected
font handle */
{
HFONT hPrevFont;
SetMapMode (hDC, MM_TEXT);
hPrevFont= SelectObject (hDC, hFont ?
hFont :
GetStockObject (SYSTEM_FIXED_FONT));
return hPrevFont;
} /* SelectFont */
/* GetFontMetrics: retrieves the TEXTMETRIC and face name of a given font */
/* ============== */
static void pascal near GetFontMetrics (HFONT hFont, TEXTMETRIC *Metrics,
char *FaceName)
/* If either Metrics of FaceName is NULL, the corresponding value is not
returned. If not NULL, FaceName must point to a string containing at
least LF_FACESIZE characters */
{
HDC hDC;
HFONT hPrevFont;
hDC = GetDC (hFrameWnd);
hPrevFont = SelectFont (hDC, hFont);
if (Metrics) GetTextMetrics (hDC, Metrics);
if (FaceName) GetTextFace (hDC, LF_FACESIZE, FaceName);
SelectObject (hDC, hPrevFont);
ReleaseDC (hFrameWnd, hDC);
} /* GetFontMetrics */
/* UpdateMaxRowCol: update the maximas displayed on the dialog box */
/* =============== */
static void pascal near UpdateMaxRowCol (HWND hDlg, HFONT hFont)
{
CellMetrics cm;
char text[17];
BuildCellMetrics (&cm, hFont);
SetDlgItemText (hDlg, ID_MAXROWS,
itoa (DisplayableRows (hFrameWnd, -1, &cm), text, 10));
SetDlgItemText (hDlg, ID_MAXCOLUMNS,
itoa (DisplayableColumns (hFrameWnd, -1, &cm), text, 10));
} /* UpdateMaxRowCol */
/* UpdateSample: Update the sample text displayed on the dialog box */
/* ============ */
static void pascal near UpdateSample (HWND hDlg, HFONT hFont,
TEXTMETRIC *m, char *FaceName)
{
#define FONTSAMPLESIZE LF_FACESIZE+40+(26*3)
char SampleText[FONTSAMPLESIZE];
int i;
char c;
strcpy (SampleText, FaceName);
i = strlen (SampleText);
strcpy (&SampleText[i], " (Height=");
i += strlen (&SampleText[i]);
itoa (m->tmHeight, &SampleText[i], 10);
i += strlen (&SampleText[i]);
strcpy (&SampleText[i], ", Width=");
i += strlen (&SampleText[i]);
itoa (m->tmAveCharWidth, &SampleText[i], 10);
i += strlen (&SampleText[i]);
strcpy (&SampleText[i], ") sample:");
i += strlen (&SampleText[i]);
for (c = 'A'; c <= 'Z'; c++) {
SampleText[i++] = ' ';
SampleText[i++] = c;
SampleText[i++] = tolower(c);
}
SampleText[i] = '\0';
SendDlgItemMessage (hDlg, ID_SAMPLE, WM_SETFONT, hFont, FALSE);
SetDlgItemText (hDlg, ID_SAMPLE, SampleText);
} /* UpdateSample */
/* NewFont: creates a font matching the user's selections */
/* ======= */
static void pascal near NewFont (HWND hDlg, BOOL TrustSizeEdit)
/* setting TrustSizeEdit to FALSE indicates that the contents of the
ID_FONTSIZE edit box should not be used (this is used when this
function is called for a size list-selection change, at which time
the edit box has not been updated yet) */
{
DWORD d;
int i;
BOOL FontSizeOK;
LOGFONT lf;
HFONT hOldFont;
hOldFont = hNewFont;
i = SendDlgItemMessage (hDlg, ID_FONT, LB_GETCURSEL, 0, 0L);
if (i == LB_ERR) lf.lfFaceName[0] = 0;
else {
SendDlgItemMessage (hDlg, ID_FONT, LB_GETTEXT, i,
(DWORD)(LPSTR)lf.lfFaceName);
}
if (TrustSizeEdit) {
i = GetDlgItemInt (hDlg, ID_FONTSIZE, &FontSizeOK, FALSE);
}
else FontSizeOK = FALSE;
if (FontSizeOK) {
lf.lfHeight = i;
lf.lfWidth = 0;
}
else {
i = SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_GETCURSEL, 0, 0L);
if (i == CB_ERR) i = 0;
d = SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_GETITEMDATA, i, 0L);
lf.lfHeight = HIWORD(d);
lf.lfWidth = LOWORD(d);
}
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = IsDlgButtonChecked (hDlg, ID_BOLD) ? 700 : 400;
lf.lfItalic = 0;
lf.lfUnderline = 0;
lf.lfStrikeOut = 0;
lf.lfCharSet = IsDlgButtonChecked (hDlg, ID_ANSI) ?
ANSI_CHARSET : OEM_CHARSET;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
hNewFont = CreateFontIndirect (&lf);
GetFontMetrics (hNewFont, &Metrics, FaceName);
UpdateMaxRowCol (hDlg, hNewFont);
UpdateSample (hDlg, hNewFont, &Metrics, FaceName);
if (hOldFont) DeleteObject (hOldFont);
} /* NewFont */
/* AddSize: Add a font size into the font size list (used by EnumSizesProc) */
/* ======= */
static void pascal near AddSize (HWND hDlg, short int Height, short int Width)
{
char ItemText[17];
int i;
itoa (Height, ItemText, 10);
i = SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_ADDSTRING, 0,
(DWORD)(LPSTR)ItemText);
SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_SETITEMDATA, i,
MAKELONG(Width,Height));
} /* AddSize */
/* EnumSizesProc: font enumeration function used by BuildSizeList */
/* ============= */
int EXPORT far pascal EnumSizesProc (LPLOGFONT lf, LPTEXTMETRIC tm,
short FontType, LPSTR Data)
/* Data should point to a handle to the dialog box */
{
if ((lf->lfWeight > 400) || lf->lfItalic || lf->lfUnderline ||
lf->lfStrikeOut) return 1;
if (FontType & 0x04) { /* SCALABLE_FONTYPE */
/* make a size list up */
short int h;
for (h = lf->lfHeight / 3; h <= lf->lfHeight; h += 2) {
AddSize (*(HWND far *)Data, h, 0);
}
return 0; /* no need to list this one further */
}
else { /* non-scalable font */
/* list it only if it has a proper aspect ratio */
HFONT hFont;
LOGFONT Font;
TEXTMETRIC Metrics;
Font = *lf;
Font.lfWidth = 0;
hFont = CreateFontIndirect (&Font);
GetFontMetrics (hFont, &Metrics, NULL);
DeleteObject (hFont);
if (tm->tmAveCharWidth == Metrics.tmAveCharWidth) {
AddSize (*(HWND far *)Data, lf->lfHeight, lf->lfWidth);
}
}
return 1;
} /* EnumSizesProc */
/* BuildSizeList: initializes the FontSize list box */
/* ============= */
static void pascal near BuildSizeList (HWND hDlg, TEXTMETRIC *Metrics)
/* This function initializes the FontSize list box with the sizes
available for the face name currently selected in the Font list box.
The sizes are written in the format: CXxCY. Also, the sizes are
stored in the 32 bit values retrievable by LB_GETITEMDATA: width in
the low-order word and height in the high order word */
{
SendDlgItemMessage (hDlg, ID_FONTSIZE, WM_SETREDRAW, FALSE, 0L);
SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_RESETCONTENT, 0, 0L);
{
HDC hDC;
FARPROC ProcInstance;
char FaceName[LF_FACESIZE];
SendDlgItemMessage (hDlg, ID_FONT, LB_GETTEXT,
SendDlgItemMessage (hDlg, ID_FONT,
LB_GETCURSEL, 0, 0L),
(DWORD)(LPSTR)FaceName);
/* FaceName now contains the currently selected face name */
hDC = GetDC (hDlg);
ProcInstance = MakeProcInstance ((FARPROC)EnumSizesProc,
hEmacsInstance);
EnumFonts (hDC, FaceName, ProcInstance, (LPSTR)&hDlg);
FreeProcInstance (ProcInstance);
ReleaseDC (hDlg, hDC);
}
SendDlgItemMessage (hDlg, ID_FONTSIZE, WM_SETREDRAW, TRUE, 0L);
InvalidateRect (GetDlgItem (hDlg, ID_FONTSIZE), NULL, TRUE);
{ /*-Select the larger height that is smaller or equal to the
current Metrics (assumed to be the ones of the previous font)
*/
int i;
int BestIndex = 0;
short int h, w, BestHeight = 0, BestWidth = 0;
DWORD ItemData;
for (i = 0;; i++) {
ItemData = SendDlgItemMessage (hDlg, ID_FONTSIZE,
CB_GETITEMDATA, i, 0L);
if (ItemData == CB_ERR) break; /* end of list hit */
if ((h = HIWORD(ItemData)) > Metrics->tmHeight) continue;
if (BestHeight > h) continue;
w = LOWORD(ItemData);
if (BestHeight == h) { /* use the width to optimize */
if (w > Metrics->tmAveCharWidth) continue;
if (BestWidth > w) continue;
}
BestHeight = h;
BestWidth = w;
BestIndex = i;
}
SendDlgItemMessage (hDlg, ID_FONTSIZE, CB_SETCURSEL, BestIndex, 0L);
}
NewFont (hDlg, TRUE);
} /* BuildSizeList */
/* AddFace: Adds a face to the FONT list box if it begets a proper font */
/* ======= */
static void pascal near AddFace (HWND hDlg, char *CandidateFace)
{
BYTE CharSet;
int From, At; /* indexes for list box searches */
HFONT hFixedFont;
char FaceName [LF_FACESIZE];
TEXTMETRIC tm;
CharSet = (IsDlgButtonChecked (hDlg, ID_ANSI) ?
ANSI_CHARSET : OEM_CHARSET);
/*-try to identify a fixed-pitch font of set CharSet, with the
specified face name */
hFixedFont = CreateFont (0, 0, 0, 0, 0, FALSE, FALSE, FALSE,
CharSet, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DRAFT_QUALITY,
FF_DONTCARE+FIXED_PITCH,
CandidateFace);
GetFontMetrics (hFixedFont, &tm, FaceName);
DeleteObject (hFixedFont);
if ((tm.tmPitchAndFamily & 0x01) || /* =1 if variable pitch */
(tm.tmCharSet != CharSet) ||
(strcmp (FaceName, CandidateFace) != 0)) {
/* flunked the exam! */
return; /* skip that face */
}
/* the candidate face has at least one fixed-pitch font with the
right charset */
/*- scan the list box to make sure this face is not a duplicate */
At = -1; /* start at beginning of list box */
do {
From = At;
At = SendDlgItemMessage (hDlg, ID_FONT, LB_FINDSTRING, From,
(DWORD)CandidateFace);
if (At == LB_ERR) break; /* no match, implies not duplicate */
if (SendDlgItemMessage (hDlg, ID_FONT, LB_GETTEXTLEN, At, 0L) ==
strlen(CandidateFace)) {
/* the lengths match, that means the strings match so it is
indeed a duplicate */
return;
}
} while (At > From); /* exit if search has gone through the
bottom of the list box */
/*-it is a brand new face, let's add it to the list */
SendDlgItemMessage (hDlg, ID_FONT, LB_ADDSTRING, 0, (DWORD)CandidateFace);
return;
} /* AddFace */
/* EnumFacesProc: face enumeration function used by BuildFaceList */
/* ============= */
int EXPORT far pascal EnumFacesProc (LPLOGFONT lf, LPTEXTMETRIC tm,
short FontType, LPSTR Data)
/* Data should point to a handle to the dialog box */
/* lists only fixed pitch fonts that match the selected charset */
{
AddFace (*(HWND far *)Data, lf->lfFaceName);
return 1;
} /* EnumFacesProc */
/* BuildFaceList: initialize the FONT list box */
/* ============= */
static void pascal near BuildFaceList (HWND hDlg, char *FaceName)
/* This function initializes the Font list box with fixed fonts matching
the current charset selection and then selects an item */
{
SendDlgItemMessage (hDlg, ID_FONTSIZE, WM_SETREDRAW, FALSE, 0L);
SendDlgItemMessage (hDlg, ID_FONT, LB_RESETCONTENT, 0, 0L);
{
HDC hDC;
FARPROC ProcInstance;
hDC = GetDC (hDlg);
ProcInstance = MakeProcInstance ((FARPROC)EnumFacesProc,
hEmacsInstance);
EnumFonts (hDC, NULL, ProcInstance, (LPSTR)&hDlg);
FreeProcInstance (ProcInstance);
ReleaseDC (hDlg, hDC);
}
SendDlgItemMessage (hDlg, ID_FONT, WM_SETREDRAW, TRUE, 0L);
InvalidateRect (GetDlgItem (hDlg, ID_FONT), NULL, TRUE);
/*-select the same facename as before or default to the first item */
if (SendDlgItemMessage (hDlg, ID_FONT, LB_SELECTSTRING, -1, FaceName)
== LB_ERR) {
SendDlgItemMessage (hDlg, ID_FONT, LB_SETCURSEL, 0, 0L);
}
BuildSizeList (hDlg, &Metrics);
} /* BuildFaceList */
/* FontDlgProc: Emacs Font dialog box function */
/* =========== */
int EXPORT far pascal FontDlgProc (HWND hDlg, WORD wMsg, WORD wParam,
DWORD lParam)
{
switch (wMsg) {
case WM_INITDIALOG:
hNewFont = NULL;
{ /*-setup the dialog box's caption */
char s[40];
strcpy (s, ProgName);
strcat (s, " - Font selection");
SetWindowText (hDlg, s);
}
/*-set the Bold button */
GetFontMetrics (hEmacsFont, &Metrics, FaceName);
CheckDlgButton (hDlg, ID_BOLD, (Metrics.tmWeight > 550));
{ /*-simulate a mouse click on the appropriate charset
radiobutton. This will initialize all the other controls
*/
WORD id;
id = (Metrics.tmCharSet == ANSI_CHARSET ? ID_ANSI : ID_OEM);
SendMessage (hDlg, WM_COMMAND, id,
MAKELONG(GetDlgItem (hDlg, id), BN_CLICKED));
}
return TRUE;
case WM_COMMAND:
switch (wParam) {
case 1: /* OK button */
if (HIWORD(lParam) == BN_CLICKED) {
AcceptFont:
if (hEmacsFont) DeleteObject (hEmacsFont);
hEmacsFont = hNewFont;
EndDialog (hDlg, TRUE);
/* no need to unhook the SAMPLE's font, it is not
destroyed since it will be used by emacs */
}
else return FALSE;
break;
case 2: /* Cancel button */
if (HIWORD(lParam) == BN_CLICKED) goto CancelFont;
else return FALSE;
case ID_SAVEFONT:
if (HIWORD(lParam) == BN_CLICKED) {
/*-save the facename, bold status and size into WIN.INI,
then perform as the OK button */
char NumText[17];
GetFontMetrics (hNewFont, &Metrics, FaceName);
WriteProfileString (ProgName, "FontName", FaceName);
WriteProfileString (ProgName, "CharSet",
itoa (Metrics.tmCharSet, NumText, 10));
WriteProfileString (ProgName, "FontHeight",
itoa (Metrics.tmHeight, NumText, 10));
WriteProfileString (ProgName, "FontWidth",
itoa (Metrics.tmAveCharWidth,
NumText, 10));
WriteProfileString (ProgName, "FontWeight",
itoa (Metrics.tmWeight, NumText, 10));
}
else return FALSE;
goto AcceptFont;
case ID_ANSI:
case ID_OEM:
if (HIWORD(lParam) == BN_CLICKED) {
CheckRadioButton (hDlg, ID_1ST_CHARSET, ID_LAST_CHARSET,
wParam);
BuildFaceList (hDlg, FaceName);
}
else return FALSE;
break;
case ID_BOLD:
if (HIWORD(lParam) == BN_CLICKED) NewFont (hDlg, TRUE);
else return FALSE;
break;
case ID_FONT:
switch (HIWORD(lParam)) {
case LBN_SELCHANGE:
BuildSizeList (hDlg, &Metrics);
break;
case LBN_DBLCLK: /* treated as OK */
goto AcceptFont;
default:
return FALSE;
}
break;
case ID_FONTSIZE:
switch (HIWORD(lParam)) {
case CBN_SELCHANGE:
NewFont (hDlg, FALSE);
break;
case CBN_EDITCHANGE:
{
BOOL FontSizeOK;
GetDlgItemInt (hDlg, ID_FONTSIZE, &FontSizeOK, FALSE);
if (FontSizeOK) NewFont (hDlg, TRUE);
else MessageBeep (0);
}
break;
case CBN_DBLCLK: /* treated as OK */
goto AcceptFont;
default:
return FALSE;
}
break;
default:
return FALSE;
}
break;
case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_CLOSE) {
CancelFont:
EndDialog (hDlg, FALSE);
if (hNewFont) {
SendDlgItemMessage (hDlg, ID_SAMPLE, WM_SETFONT, 0, FALSE);
/* reset to SYSTEM_FONT before deleting the font */
DeleteObject (hNewFont);
}
return TRUE;
}
return FALSE;
default:
return FALSE;
}
return FALSE;
} /* FontDlgProc */
/* ChangeFont: effects the font change on the screen & message line */
/* ========== */
static void pascal near ChangeFont (void)
{
SCREEN *sp, *fsp;
RECT Rect;
/*-loop through all the screens, resizing the vision that emacs has
of them, processing the current ("first") screen last */
InternalRequest = TRUE;
fsp = first_screen;
do {
sp = first_screen;
while (sp->s_next_screen != (SCREEN *)NULL) sp = sp->s_next_screen;
select_screen (sp, FALSE);
GetClientRect (sp->s_drvhandle, &Rect);
newwidth (TRUE, DisplayableColumns (sp->s_drvhandle,
Rect.right, &EmacsCM));
newsize (TRUE, DisplayableRows (sp->s_drvhandle,
Rect.bottom, &EmacsCM));
} while (sp != fsp);
InternalRequest = FALSE;
/*-update the frame's client area and the MDIClient's size */
InvalidateRect (hFrameWnd, NULL, TRUE);
GetClientRect (hFrameWnd, &Rect);
MoveWindow (hMDIClientWnd, 0, 0,
Rect.right, Rect.bottom - EmacsCM.MLHeight,
TRUE);
} /* ChangeFont */
/* PickEmacsFont: calls-up the FONTS dialog box */
/* ============= */
BOOL far pascal PickEmacsFont (void)
/* returns TRUE is a new font has been picked */
{
BOOL FontChanged;
FARPROC ProcInstance;
ProcInstance = MakeProcInstance ((FARPROC)FontDlgProc,
hEmacsInstance);
FontChanged = DialogBox (hEmacsInstance, "FONTS",
hFrameWnd, ProcInstance);
FreeProcInstance (ProcInstance);
if (FontChanged) {
BuildCellMetrics (&EmacsCM, hEmacsFont);
ChangeFont ();
return TRUE;
}
else return FALSE;
} /* PickEmacsFont */
/* FontInit: initialize a font description from WIN.INI */
/* ======== */
void far pascal FontInit (void)
{
LOGFONT lf;
char text[20];
if (GetProfileString (ProgName, "CharSet", "", text, 20)) {
if (isdigit(text[0])) { /* pure numeric value */
lf.lfCharSet = atoi (text);
}
else { /* menmonic value */
if (strncmp (text, "OEM", 3) == 0) {
lf.lfCharSet = OEM_CHARSET;
}
else lf.lfCharSet = ANSI_CHARSET;
}
lf.lfHeight = GetProfileInt (ProgName, "FontHeight", 0);
lf.lfWidth = GetProfileInt (ProgName, "FontWidth", 0);
lf.lfEscapement = 0;
lf.lfOrientation = 0;
lf.lfWeight = GetProfileInt (ProgName, "FontWeight", 400);
lf.lfItalic = 0;
lf.lfUnderline = 0;
lf.lfStrikeOut = 0;
lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
lf.lfQuality = DEFAULT_QUALITY;
lf.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
GetProfileString (ProgName, "FontName", "",
lf.lfFaceName, LF_FACESIZE);
hEmacsFont = CreateFontIndirect (&lf);
}
else { /* no CharSet entry, default to SYSTEM_FIXED_FONT */
hEmacsFont = 0;
}
BuildCellMetrics (&EmacsCM, hEmacsFont);
} /* FontInit */